<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>H5指北针（指南针）演示程序</title>
  <meta name="viewport" content="initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
</head>

<body>
  <div id="compass"></div>
  <script type="text/javascript" src="./raphael.js"></script>
  <script type="text/javascript" src="./hammer.min.js"></script>
  <script>
    //计算屏幕宽度 高度
    var pageWidth = window.innerWidth;
    var pageHeight = window.innerHeight;
    if (typeof pageWidth != "number") {
      if (document.compatMode == "CSS1Compat") {
        pageWidth = document.documentElement.clientWidth;
        pageHeight = document.documentElement.clientHeight;
      } else {
        pageWidth = document.body.clientWidth;
        pageHeight = document.body.clientHeight;
      }
    }
    var zoom = 1;
    //compass div 宽高
    var paperWidth = 300;
    var paperHeight = 300;
    var crLong = 130 * zoom;
    var crShort = 100 * zoom;
    var cdiff = paperHeight / 2 - crLong;
    var initX = (pageWidth - paperWidth) > 0 ? (pageWidth - paperWidth) / 2 : 0;
    var initY = (pageHeight - paperHeight) > 0 ? (pageHeight - paperHeight) / 2 : 0;
    document.getElementById("compass").style.marginTop = initY + "px";
    document.getElementById("compass").style.marginLeft = initX + "px";

    //创建画布
    var compassPaper = Raphael(initX, initY, paperWidth, paperHeight)
    //画园
    compassPaper.circle(paperWidth / 2, paperHeight / 2, crLong).attr('fill', 'black');

    var cross = compassPaper.set()
    var crossStyle = {
      stroke: 'white',
      'stroke-width': 1
    }
    //指南针画十字
    var pathlineX = 'M' + (paperWidth / 2 - crShort / 2) + ' ' + (paperHeight / 2) + 'L' + (paperWidth / 2 + crShort / 2) + ' ' + (paperHeight / 2);
    var pathlineY = 'M' + (paperWidth / 2) + ' ' + (paperHeight / 2 - crShort / 2) + 'L' + (paperWidth / 2) + ' ' + (paperHeight / 2 + crShort / 2);
    var northline = 'M' + (paperWidth / 2) + ' ' + (paperHeight / 2 - crShort) + 'L' + (paperWidth / 2) + ' ' + (crLong - crShort);

    cross.push(
      compassPaper.path(pathlineX).attr(crossStyle),
      compassPaper.path(pathlineY).attr(crossStyle)
    )
    //指北线
    var northBar = compassPaper.path(northline).attr({
      stroke: 'white',
      'stroke-width': 4
    })
    var compass = compassPaper.set()
    var strokeWidth
    var billet
    var degText
    for (var i = 0; i < 360; i = i + 2) {
      if (i % 30 == 0) {
        strokeWidth = 2
        degText = compassPaper.text(paperWidth / 2, (paperHeight / 2 - crShort) * 4 / 5, i).attr({
          fill: 'white',
          'font-size': '16rem'
        }).transform('R' + i + ', ' + paperWidth / 2 + ', ' + paperHeight / 2)
        degText.degPosition = i
        compass.push(degText)
      } else {
        strokeWidth = 1
      }
      billet = compassPaper.path('M' + paperWidth / 2 + ' ' + (paperHeight / 2 - crShort) + 'L' + paperWidth / 2 + '  ' + (paperHeight / 2 - crShort + crShort / 5)).attr({
        stroke: 'white',
        'stroke-width': strokeWidth
      }).transform('R' + i + ',' + paperWidth / 2 + ', ' + paperHeight / 2)
      billet.degPosition = i
      compass.push(
        billet
      );
    }
    ['N', 'E', 'S', 'W'].forEach(function (direction, index) {
      var directionText = compassPaper.text(paperWidth / 2, (paperHeight / 2 - crShort + crShort / 3), direction).attr({
        fill: 'white',
        'font-size': '20rem'
      }).transform('R' + index * 90 + ', ' + (paperWidth / 2) + ',' + paperHeight / 2)
      directionText.degPosition = index * 90
      compass.push(directionText)
    })

    var redTriLine = 'M' + (paperWidth / 2) + ' ' + ((paperHeight / 2 - crLong) + cdiff / 2) + ' L' + (paperWidth / 2 - (paperHeight / 2 - crShort) / 4) + ' ' + (paperHeight / 2 - crShort) + ' L' + (paperWidth / 2 + (paperHeight / 2 - crShort) / 4) + ' ' + (paperHeight / 2 - crShort) + 'Z';
    var redTriangle = compassPaper.path(redTriLine).attr({
      fill: 'red',
      'stroke-width': 0
    })
    redTriangle.degPosition = 0
    compass.push(redTriangle)

    var alphaText = compassPaper.text((paperWidth / 2), 440, '0°').attr({
      fill: 'blue',
      'font-size': '30rem'
    })

    function throttle(method, delay, duration) {
      var timer = null,
        begin = new Date();
      return function () {
        var context = this,
          args = arguments,
          current = new Date();;
        clearTimeout(timer);
        if (current - begin >= duration) {
          method.apply(context, args);
          begin = current;
        } else {
          timer = setTimeout(function () {
            method.apply(context, args);
          }, delay);
        }
      }
    }

    function deviceOrientationListener(event) {
      // console.log('event', event);
      var alpha = event.webkitCompassHeading || event.alpha;
      alpha = 365 - alpha;
      alphaText.attr({
        text: parseInt(alpha) + '°'
      });
      var directionIndex
      if (alpha > 337.5 || alpha < 22.5) {
        directionIndex = 0
      } else if (alpha > 45 - 22.5 && alpha < 45 + 22.5) {
        directionIndex = 1
      } else if (alpha > 90 - 22.5 && alpha < 90 + 22.5) {
        directionIndex = 2
      } else if (alpha > 135 - 22.5 && alpha < 135 + 22.5) {
        directionIndex = 3
      } else if (alpha > 180 - 22.5 && alpha < 180 + 22.5) {
        directionIndex = 4
      } else if (alpha > 225 - 22.5 && alpha < 225 + 22.5) {
        directionIndex = 5
      } else if (alpha > 270 - 22.5 && alpha < 270 + 22.5) {
        directionIndex = 6
      } else if (alpha > 315 - 22.5 && alpha < 315 + 22.5) {
        directionIndex = 7
      }
      compass.forEach(function (item) {
        item.transform('R' + (item.degPosition - alpha) + ',' + (paperWidth / 2) + ', ' + paperHeight / 2)
      })
    }

    //手机是否支持重力事件
    if (window.DeviceOrientationEvent) {
      window.addEventListener('deviceorientation', throttle(deviceOrientationListener, 20, 35))
      // window.addEventListener('deviceorientation', deviceOrientationListener)
    } else {
      alert("Sorry your browser doesn't support Device Orientation");
    }
  </script>
</body>

</html>